各位好,時間過得有點快沒想到已經 Day14 了!,不知道時間夠不夠達成我當初設定的目標呢?
那麼今天就繼續把 ownership 的概念完成吧!今天要講的是 ownership 在函式裡面的轉移方式,Let'go!
傳遞值給函式(function)時其實跟我們把值 assign 給變數時是類似的方式,也就是說當把值傳給函式時同樣會用 move 或是 copy 的方法處理,那麼我們就直接看個例子,
fn ownership_and_functions() {
let s = String::from("hello"); // s 現在在 scope 裡面
takes_ownership(s); // 由於 s 是用 heap 法處理所以 move
// 因此 s 的所有權已經被轉移了
println!("s = {}", s); // 這時已經取得不了 s 編譯會報錯
^ value borrowed here after move
let x = 5; // 反之如果是 stack 法處理
makes_copy(x); // x 就會 copy 一份後進到函式裡面
// 所以還是可以印得出 x 不會報錯
println!("x = {}", x);
}
fn takes_ownership(some_string: String) {
println!("{}", some_string);
}
fn makes_copy(some_integer: i32) {
println!("{}", some_integer);
}
如果我們試著取得 s 在他 move 所有權之後編譯器就會報錯反之如果是用 copy 的方式處理的就不會。
而同樣當函式返回值的時候也會轉移所有權,例如下面的例子,
fn ownership_and_return_values() {
let s1 = gives_ownership(); // s1 的所有權是從 gives_ownership 來的
// 其值為 "hello"
let s2 = String::from("hello"); // 宣告一個新的變數 s2
let s3 = takes_and_gives_back(s2); // s2 move 進 takes_and_gives_back
// takes_and_gives_back, 同時也返回所有權
// 現在 s3 有所有權
println!("{}", s2); // 報錯因為 s2 的所有權已經轉移給 s3
println!("{}", s3); // 不會報錯 s3 擁有所有權
}
fn gives_ownership() -> String {
// gives_ownership 這支程式將會把 some_string 的擁有權
// 傳出去給呼叫他的另外一個擁有者
let some_string = String::from("hello"); // 宣告一個新的變數 some_string
some_string // 返回 some_string
// move 出去給呼叫他的擁有者
}
// 直接返回傳入的值
fn takes_and_gives_back(a_string: String) -> String {
a_string
}
也就是說 ownership (所有權)會在函式之中被傳來傳去,但是同時也造成麻煩例如,
fn main() {
let s1 = String::from("hello");
let (s2, len) = calculate_length(s1);
println!("The length of '{}' is {}.", s2, len);
}
// 如果我們還需要使用 s 時必須再把他回傳
fn calculate_length(s: String) -> (String, usize) {
let length = s.len(); // 算出 String 的長度
(s, length)
}
這樣的方式太攏長會造成寫程式時的不便,因此接下來會介紹 Rust reference 的概念。
今天介紹了 ownership 如何在函式裡面傳遞但是同時也造成了一些麻煩,所以下一篇我們會來介紹怎麼比較好的處理這樣的情況也就是 References and Borrowing 的概念。
那麼我們明天見!